﻿using System.Collections.Concurrent;
using System.Text.Json;

namespace AiSk.Impl
{
    public class QianfanService : BaseLLmService
    {
        private record QianfanResponseModel(string id, string @object, long created, string result, bool is_truncated, bool need_clear_history, QianfanUsageModel usage);
        private record QianfanMessageModel(string role, string content);
        private record QianfanUsageModel(int prompt_tokens, int completion_tokens, int total_tokens);

        private record ApiToken(string refresh_token, int expires_in, string session_key, string access_token, string scope, string session_secret);

        private static IDictionary<string, ApiToken> tokenCache = new ConcurrentDictionary<string, ApiToken>();

        private bool CacheToken = true;
        private string ApiKey = "03PTTvjW0oForSIP4BVNQszt";
        private string ApiSecret = "Ev9SnTfqvpkDIbHHun2H2S3FrhzV1K4T";
        private string OtherArgs = "grant_type=client_credentials";
        private bool IsStream = true;
        private string qianfanTokenUrl = "https://aip.baidubce.com/oauth/2.0/token";
        private async Task<string> GetToken()
        {
            var requestData = $"client_id={ApiKey}&client_secret={ApiSecret}&{OtherArgs}";
            if (CacheToken)
            {
                var hashKey = requestData.GetHashCode().ToString();
                if (tokenCache.TryGetValue(hashKey, out var token))
                {
                    return token.access_token;
                }
            }
            var res = await new HttpClient().Request<ApiToken>(qianfanTokenUrl, "POST", requestData);
            if (res.HttpResponseMsg.IsSuccessStatusCode)
            {
                var obj = res.Result;
                if (CacheToken)
                {
                    var hashKey = requestData.GetHashCode().ToString();
                    tokenCache[hashKey] = obj!;
                }
                Console.WriteLine($"千帆token {obj!.access_token}");
                return obj!.access_token;
            }
            else
            {
                return await res.HttpResponseMsg.Content.ReadAsStringAsync();
            }
        }


        public override async Task Chat(string question,string system, string model= "ernie_speed")
        {
            var apiToken = await GetToken();
            var prompt = question;
            var userid = "111";
            var contextMessage = "";
            var temperature = "0.1";
            var top_p = "0";
            var contextList = string.IsNullOrWhiteSpace(contextMessage) ?
                new List<QianfanMessageModel>() :
                JsonSerializer.Deserialize<List<QianfanMessageModel>>(contextMessage) ?? new List<QianfanMessageModel>();
            contextList.Add(new QianfanMessageModel("user", prompt));
            var url = $"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model}";
            var otherArgs = "sourceVer=0.0.1&source=app_center&appName=streamDemo";
            var requestUrl = $"{url}?access_token={apiToken}&{otherArgs}";
            var requestData = new
            {
                userid = string.IsNullOrWhiteSpace(userid) ? string.Empty : userid,
                messages = contextList,
                stream = IsStream,
                temperature = float.Parse(temperature),
                top_p = float.Parse(top_p),
                system = string.IsNullOrWhiteSpace(system) ? string.Empty : system.Replace("%s", prompt)
            };
            if (!IsStream)
            {
                var res = await new HttpClient().Request<QianfanResponseModel>(requestUrl, "POST", requestData);
                Console.WriteLine($"返回结果 {res.Result?.result ?? string.Empty}");
            }
            else
            {
                var res = await new HttpClient().RequestStream(requestUrl, "POST", requestData);
                var task = Task.Run(async () =>
                {
                    using var reader = new StreamReader(res.Result);
                    while (!reader.EndOfStream)
                    {
                        var line = await reader.ReadLineAsync();

                        if (string.IsNullOrWhiteSpace(line))
                            continue;
                        if (line.StartsWith("data:"))
                            line = line[5..];
                        Console.WriteLine($"返回流式数据 line：{line}");
                    }
                });


                task.Wait();
            }
        }

        public override async Task Embeddings()
        {
            var token = await GetToken();
            var requestUrl = $"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/embedding-v1?access_token={token}";
            var requestData = new
            {
                input = new string[] { "推荐一些美食", "给我讲个故事" }
            };
            var res = await new HttpClient().Request(requestUrl, "POST", requestData);
            Console.WriteLine($"向量查询结果 {res.Result}");
        }

        private record QianfanStableDiffusionResponse(string id,
            string @object, long created, QianfanStableDiffusionData[]? data, QianfanUsage usage);
        private record QianfanStableDiffusionData(string @object, string b64_image, int index);
        private record QianfanUsage(int prompt_tokens, int total_tokens);
        public override async Task StableDiffusion(string question)
        {
            var token = await GetToken();
            var requestUrl = $"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/text2image/sd_xl?access_token={token}";
            var requestData = new
            {
                prompt = question,
                size = "1024x1024",
                n = 1,
                steps = 20,
                sampler_index = "Euler a"
            };
            var res = await new HttpClient().Request<QianfanStableDiffusionResponse>(requestUrl, "POST", requestData);
            Console.WriteLine($"向量查询结果 {res.Result}");
            SaveFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Guid.NewGuid().ToString("N") + ".jpg"), res.Result.data.FirstOrDefault().b64_image);
        }
        private void SaveFile(string filePath, string base64String)
        {
            // 将Base64字符串解码为字节数组
            byte[] imageBytes = Convert.FromBase64String(base64String);

            // 创建文件流并写入字节数组
            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                fs.Write(imageBytes, 0, imageBytes.Length);
                Console.WriteLine("Image saved successfully.");
            }
        }
    }
}
